﻿using System;
using System.Collections.Generic;
using System.IO;

namespace Transforms.Core
{
    public class DataSourceList //: IEnumerable<IDataSource>
    {
        private readonly Dictionary<string, IDataSource> _sources = new Dictionary<string, IDataSource>();

        public event Logger OnLog;
        public event NewItemEvent OnNewItem;
        public event NewItemEvent OnRemoveItem;

        public Func<int, string> DoGetNewName;

        public long CommonLenth { get; private set; }

        private void DoLog(string text, params object[] args)
        {
            if (OnLog != null)
                OnLog(string.Format(text, args));
        }

        public string Add(string name, IDataSource item)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentException("name is empty");

            if (name.IndexOfAny(Path.GetInvalidPathChars()) != -1)
                throw new ArgumentException("invalid name: [" + name + "]");

            if (item == null)
                throw new ArgumentNullException("item");

            var newName = GetNewName(name);
            _sources.Add(newName, item);
            CommonLenth += item.Length;

            DoLog("[DataSourceList].[Add]: {0} - {1}", newName, item);

            if (OnNewItem != null)
                OnNewItem(newName, item);

            return newName;
        }

        public Dictionary<string, IDataSource>.Enumerator GetEnumerator()
        {
            return _sources.GetEnumerator();
        }

        private string GetNewName(string name)
        {
            Func<int, string> nameGiver;

            if (DoGetNewName == null)
            {
                var extension = FileUtils.GetExtension(name) ?? "";
                var nameBody = extension == string.Empty ? name : name.Remove(name.Length - extension.Length);
                nameGiver = index => index == 0 ? name : string.Format("{0}_{1}{2}", nameBody, index, extension);
            }
            else
                nameGiver = DoGetNewName;

            var newName = nameGiver(0);
            var counter = 1;
            while (_sources.ContainsKey(newName))
            {
                newName = nameGiver(counter);
                counter++;
            }

            return newName;
        }

        public IDataSource GetSource(string fileName)
        {
            return _sources[fileName];
        }

        public void Remove(string name)
        {
            var item = _sources[name];
            CommonLenth -= item.Length;

            _sources.Remove(name);

            if (OnRemoveItem != null)
                OnRemoveItem(name, item);
        }

        public int Count
        {
            get { return _sources.Count; }
        }
    }
}